package com.example.springsecutity_demo_0904.config;

import com.example.springsecutity_demo_0904.secutity.LoginFailureHandler;
import com.example.springsecutity_demo_0904.secutity.LoginSuccessHandler;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.provisioning.JdbcUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import javax.sql.DataSource;
import java.io.IOException;

@Configuration
@EnableWebSecurity //@EnableWebSecurity 开启SpringSecurity之后会默认注册大量的过滤器
public class SecurityConfig {

    @Autowired
    DataSource dataSource;
    /**
     * inMemoryUserDetailsManager: 用户信息配置
     * 配置UserDetails的信息
     * @return
     */
    @Bean
    public UserDetailsService userDetailsService(){
        JdbcUserDetailsManager userDetailsManager = new JdbcUserDetailsManager();
        userDetailsManager.setDataSource(dataSource);
        UserDetails johnuserDetails = User.withUsername("john").password("123").authorities("admin:api", "user:api").build();
        UserDetails caryuserDetails = User.withUsername("cary").password("123").authorities("user:api").build();

        if (!userDetailsManager.userExists("admin") && !userDetailsManager.userExists("user")){
            userDetailsManager.createUser(johnuserDetails);
            userDetailsManager.createUser(caryuserDetails);
        }
        return userDetailsManager;
    }

    /**
     * 密码编译器，当前为不进行加密
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return NoOpPasswordEncoder.getInstance();
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{
        /**
         * authorizeHttpRequests: 针对Http请求进行授权配置
         * authenticated： 认证
         * anyRequest: 所有请求
         * 配置登录页面可以访问，其他所有的请求都需要权限。
         */
        http.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry ->
                authorizationManagerRequestMatcherRegistry
                        .requestMatchers("/admin/api").hasAuthority("admin:api")
                        .requestMatchers("/user/api").hasAnyAuthority("admin:api","user:api")
                        .requestMatchers("/app/api").permitAll()
                        .requestMatchers("/login").permitAll()
                        .anyRequest().authenticated()
                );
        /**
         * loginPage: 登录页面
         * loginProcessingUrl: 登录接口，过滤器
         * successHandler: 登录成功处理器
         * failureHandler: 登录失败处理器
         */
        http.formLogin(httpSecurityFormLoginConfigurer ->
                httpSecurityFormLoginConfigurer
                        .loginProcessingUrl("/login").permitAll()
                        .successHandler(new LoginSuccessHandler())
                        .failureHandler(new LoginFailureHandler())
                );
        http.logout(logout->logout
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login?logout")
                .invalidateHttpSession(true)
        );
        http.csrf(csrf->csrf.disable());//csrf防御
        http.cors(cors -> cors.disable()); //关闭跨域拦截
//        http.exceptionHandling(e->e.accessDeniedPage("/noAuth"));
        return http.build();
    }
}
